package com.study.ming;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.lang.reflect.Method;
import java.util.*;

/**
 * @author yh
 * @date 2022/10/12 15:02
 **/
@SpringBootApplication
//@EnableEurekaClient
@EnableConfigServer
public class CloudConfigServerApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext applicationContext = SpringApplication.run(CloudConfigServerApplication.class, args);
        RequestMappingHandlerMapping mapping = applicationContext.getBean(RequestMappingHandlerMapping.class);
        // 获取url与类和方法的对应信息
        Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods();

        List<MappingInfo> list = new ArrayList<>(map.size());

        for (Map.Entry<RequestMappingInfo, HandlerMethod> m : map.entrySet()) {
            MappingInfo mappingInfo = new MappingInfo();
            RequestMappingInfo info = m.getKey();
            HandlerMethod handlerMethod = m.getValue();
            //获取当前方法所在类名
            Class<?> bean = handlerMethod.getBeanType();
            //使用反射获取当前类注解内容
            RequestMapping requestMapping = bean.getAnnotation(RequestMapping.class);
            if(null != requestMapping){
                String[] value = (String[]) AnnotationUtils.getAnnotationAttributes(requestMapping).get("value");
                mappingInfo.setClassRequestMappings(Arrays.asList(value));
            }
            //获取方法上注解以及注解值
            ArrayList<Object> objects = new ArrayList<>();
            Collection<Object> objects1 = Collections.synchronizedCollection(objects);
            List<Object> objects2 = Collections.unmodifiableList(objects);
//            PatternsRequestCondition p = info.getPatternsCondition();
            List<String> urls = new ArrayList<>();
//            urls.addAll(p.getPatterns());
            mappingInfo.setRequestMappings(urls);

            mappingInfo.setClassName(handlerMethod.getMethod().getDeclaringClass());
            mappingInfo.setMethod(handlerMethod.getMethod());
            RequestMethodsRequestCondition methodsCondition = info.getMethodsCondition();

            List<String> httpMethods = new ArrayList<>();
            methodsCondition.getMethods().forEach(requestMethod -> httpMethods.add(requestMethod.toString()));
            mappingInfo.setHttpMethods(httpMethods);

            list.add(mappingInfo);
        }


        System.out.println(list);

    }
    static class MappingInfo{
        private Class<?> className; //类
        private Method method;//方法
        private List<String> httpMethods;//http方法，同一个接口可以通过GET/POST访问
        private List<String> classRequestMappings;//class定义的映射
        private List<String> requestMappings;//具体的每个映射，不包含context-path，但是包含类上的

        public Class<?> getClassName() {
            return className;
        }

        public void setClassName(Class<?> className) {
            this.className = className;
        }

        public Method getMethod() {
            return method;
        }

        public void setMethod(Method method) {
            this.method = method;
        }

        public List<String> getHttpMethods() {
            return httpMethods;
        }

        public void setHttpMethods(List<String> httpMethods) {
            this.httpMethods = httpMethods;
        }

        public List<String> getClassRequestMappings() {
            return classRequestMappings;
        }

        public void setClassRequestMappings(List<String> classRequestMappings) {
            this.classRequestMappings = classRequestMappings;
        }

        public List<String> getRequestMappings() {
            return requestMappings;
        }

        public void setRequestMappings(List<String> requestMappings) {
            this.requestMappings = requestMappings;
        }

        @Override
        public String toString() {
            return "MappingInfo{" +
                    "className=" + className +
                    ", method=" + method +
                    ", httpMethods=" + httpMethods +
                    ", classRequestMappings=" + classRequestMappings +
                    ", requestMappings=" + requestMappings +
                    '}';
        }
    }
}
